#!/usr/bin/env python3
# encoding: utf-8

from enum import Enum
from typing import List

FINAL_MONSTER_COUNT = 3 # 最终的妖怪数
FINAL_MONK_COUNT = 3 # 最终的和尚数

class BOAT_LOCATION(Enum):
    """
    船的位置
    """
    LOCAL = 0
    REMOTE = 1

class ACTION_NAME(Enum):
    """
    每次移动船动作的名称
    """
    ONE_MONSTER_GO = 0
    TWO_MONSTER_GO = 1
    ONE_MONK_GO = 2
    TWO_MONK_GO = 3
    ONE_MONSTER_ONE_MONK_GO = 4
    ONE_MONSTER_BACK = 5
    TWO_MONSTER_BACK = 6
    ONE_MONK_BACK = 7
    TWO_MONK_BACK = 8
    ONE_MONSTER_ONE_MONK_BACK = 9
    INVALID_ACTION_NAME = 10

class ACTION_EFFECTION():
    """
    移动动作的状态
    """
    def __init__(self, 
                act: ACTION_NAME, 
                boat_to: BOAT_LOCATION, 
                move_monster: int,
                move_monk: int): 
        self.act = act
        self.boat_to = boat_to
        self.move_monster = move_monster
        self.move_monk = move_monk

class ACTION_DESCRIPTION():
    """
    动作的描述
    """
    def __init__(self, act: ACTION_NAME, description: str):
        self.act = act
        self.description = description

actDesc: List[ACTION_DESCRIPTION] = [
    ACTION_DESCRIPTION(ACTION_NAME.ONE_MONSTER_GO, "One monster go over river"),
    ACTION_DESCRIPTION(ACTION_NAME.TWO_MONSTER_GO, "Two monster go over river"),
    ACTION_DESCRIPTION(ACTION_NAME.ONE_MONK_GO, "One monk go over river"),
    ACTION_DESCRIPTION(ACTION_NAME.TWO_MONK_GO, "Two monk go over river"),
    ACTION_DESCRIPTION(ACTION_NAME.ONE_MONSTER_ONE_MONK_GO, "One monster and one monk go over river"),
    ACTION_DESCRIPTION(ACTION_NAME.ONE_MONSTER_BACK, "One monster go back"),
    ACTION_DESCRIPTION(ACTION_NAME.TWO_MONSTER_BACK, "Two monster go back"),
    ACTION_DESCRIPTION(ACTION_NAME.ONE_MONK_BACK, "One monk go back"),
    ACTION_DESCRIPTION(ACTION_NAME.TWO_MONK_BACK, "Two monk go back"),
    ACTION_DESCRIPTION(ACTION_NAME.ONE_MONSTER_ONE_MONK_BACK, "One monster and on monk go back"),
]

def GetActionDescription(act: ACTION_NAME):
    """
    获取动作描述
    """
    for des in actDesc:
        if des.act == act:
            return des.description 

    return "Unknown action"

class ItemState:
    """
    状态类
    """
    def __init__(self,
                local_monster: int,
                local_monk: int,
                remote_monster: int,
                remote_monk: int,
                boat: BOAT_LOCATION):
        self.local_monster = local_monster
        self.local_monk = local_monk
        self.remote_monster = remote_monster
        self.remote_monk = remote_monk
        self.boat = boat
        self.curAct = ACTION_NAME.INVALID_ACTION_NAME

    def SetState(self, lmonster: int, lmonk: int, rmonster: int, rmonk: int, bl: BOAT_LOCATION):
        self.local_monster = lmonster
        self.local_monk = lmonk
        self.remote_monster = rmonster
        self.remote_monk = rmonk
        self.boat = bl

    def PrintStates(self):
        print(GetActionDescription(self.curAct))

    def IsSameState(self, state: ItemState) -> bool:
        """
        是否是一样的状态
        """
        return self.local_monster == state.local_monster \
            and self.local_monk == state.local_monk \
            and self.remote_monster == state.remote_monster \
            and self.remote_monk == state.remote_monk \
            and self.boat == state.boat

    def IsFinalState(self) -> bool:
        """
        是否是最终的状态
        """
        return self.local_monster == 0 and self.local_monk == 0 \
            and self.remote_monster == FINAL_MONSTER_COUNT \
            and self.remote_monk == FINAL_MONK_COUNT \
            and self.boat == BOAT_LOCATION.REMOTE

    def IsValidState(self) -> bool:
        """
        是否是有效的状态
        """
        if self.local_monk > 0 and self.local_monster > self.local_monk:
            return False

        if self.remote_monk > 0 and self.remote_monster > self.remote_monk:
            return False

        return True
        

    def CanTakeAction(self, ae: ACTION_EFFECTION) -> bool:
        """
        能否进行此动作
        """
        if self.boat == ae.boat_to:
            return False

        if (self.local_monster + ae.move_monster) < 0 or (self.local_monster + ae.move_monster) > FINAL_MONSTER_COUNT:
            return False

        if (self.local_monk + ae.move_monk) < 0 or (self.local_monk + ae.move_monk) > FINAL_MONK_COUNT:
            return False

        return True
        
"""
实际操作代码
"""
